
#include "subprocess.h"
#include <stdio.h>
#include <Windows.h>


int create_subprocess(struct process_config *config)
{
	int i;
    TCHAR cmdline2[1000];
    TCHAR *Args = NULL;
    TCHAR cmdline3[1000];
    TCHAR *Env = NULL;
    PROCESS_INFORMATION stProcessInfo;
    STARTUPINFO stStartUpInfo = {sizeof(STARTUPINFO)};

	HANDLE cmdInput = NULL;
    HANDLE cmdOutput = NULL;
    HANDLE cmdErrput = NULL;

    SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};
    if(NULL != config->output_path)
    {
        cmdOutput = CreateFile(config->output_path,
                            GENERIC_WRITE,
                            FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                            &sa,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
        if(cmdOutput == INVALID_HANDLE_VALUE)
        {
            ExitProcess(0);
        }
        cmdErrput = cmdOutput;
    }
    if(NULL != config->input_path)
    {
        cmdInput = CreateFile(config->input_path,
                            GENERIC_READ,
                            FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                            &sa,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
        if(cmdInput == INVALID_HANDLE_VALUE)
        {
            ExitProcess(0);
        }
    } 
 
	for(i=0; i<ARGS_MAX_NUMBER; i++)
    {
        int len = 0;
        if(NULL == config->args[i])
            break;
        Args = cmdline2;
        len += sprintf(cmdline2+len,"%s ", config->args[i]);
    }

    for(i=0; i<ENV_MAX_NUMBER; i++)
    {
        int len = 0;
        if(NULL == config->env[i])
            break;
        Env = cmdline3;
        len += sprintf(cmdline3+len,"%s ", config->env[i]);
    }

    if(config->max_cpu_time == UNLIMITED)
        config->max_cpu_time = INFINITE;

	stStartUpInfo.hStdInput = cmdInput;
	stStartUpInfo.hStdOutput = cmdOutput;
    stStartUpInfo.hStdError = cmdOutput;
	stStartUpInfo.dwFlags = STARTF_USESTDHANDLES;
    DWORD flags = CREATE_NO_WINDOW;

	if(CreateProcess(NULL, Args,NULL,NULL,TRUE,flags,NULL,//Env,
                    NULL,&stStartUpInfo,&stProcessInfo))
	{
        // 等待退出
		WaitForSingleObject(stProcessInfo.hProcess,config->max_cpu_time);
		// 获取子进程的退出码 
        long unsigned int dwExitCode;
        GetExitCodeProcess(stProcessInfo.hProcess, &dwExitCode);
        //终止进程
        TerminateProcess(stProcessInfo.hProcess, 0);
        // 关闭子进程的主线程句柄 
        CloseHandle(stProcessInfo.hThread);
        // 关闭子进程句柄 
		CloseHandle(stProcessInfo.hProcess);        
	}
	else
	{
		//如果创建进程失败，查看错误码
        DWORD dwErrCode = GetLastError();
        printf("ErrCode : %d\n", dwErrCode);
	}
	
 	if(NULL != config->output_path)
    {
        FlushFileBuffers(cmdOutput);
        CloseHandle(cmdOutput);
    }
    if(NULL != config->input_path)
    {
        FlushFileBuffers(cmdOutput);
        CloseHandle(cmdInput);
    }
 
	return 0;
}



void process_config_test(struct process_config *config)
{
    /* 最长CPU 运行时间*/
    config->max_cpu_time = UNLIMITED;
    /* 实际 最大 运行时间*/
    config->max_real_time = UNLIMITED;
    /* 最大虚内存 */
    config->max_memory = UNLIMITED;

#if 1
    /* MS */
    config->max_cpu_time = 1000;
    config->max_cpu_time = 3000;
    config->max_cpu_time = 128 * 1024 * 1024;
    config->max_cpu_time = 32 * 1024 * 1024;    
    config->max_cpu_time = 1024 * 1024;
	config->max_cpu_time = 10000;
#endif
    /*  */
    config->memory_limit_check_only = 0;

    /* 进程堆栈资源限制 */
    config->max_stack = 16 * 1024 * 1024;

    /* 进程最大值 */
    config->max_process_number = UNLIMITED;

    /* 输出最大值 */
    config->max_output_size = UNLIMITED;

    /* 程序执行路径  */
    config->exe_path = "test1.exe";

    /* 输入文件 */
    config->input_path = "input.txt";

    /* 输出文件 */
    config->output_path = "output.txt";

    /* 错误输出文件 */
    config->error_path = "/dev/stderr";

    /* 输入参数 */
    config->args[0] = config->exe_path;
    config->args[1] = NULL;
    //config->env[0] = "PATH=/usr/local/bin:/usr/bin:/bin";
    config->env[0] = "C:\\Program Files\\Common Files\\Oracle\\Java\\javapath;D:\\Program Files\\VanDyke Software\\Clients\\;%SystemRoot%\\system32;%SystemRoot%;%SystemRoot%\\System32\\Wbem;%SYSTEMROOT%\\System32\\WindowsPowerShell\v1.0\\;C:\\ProgramData\\DockerDesktop\\version-bin;D:\\Program Files\\Java\\jdk-11.0.9\bin;";
    config->env[1] = "LANG=en_US.UTF-8";
    config->env[2] = "LC_ALL=en_US.UTF-8";
    config->env[3] = NULL;

    /* 日志 */
    config->log_path = "judger.log";
    
    config->seccomp_rule_name = "c_cpp";
    config->uid = 0;
    config->gid = 0;

}

int main()
{
    int a;
    struct process_config config;
    process_config_test(&config);
    create_subprocess(&config);
    printf("Hello World \n");
}